-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Task cancellation shields #3037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Introduce a proposal for task cancellation shields to allow certain code to execute regardless of task cancellation status. Implementation WIP PR: swiftlang/swift#85637
Updated reference to SE-0493 to include a link.
| public func withTaskCancellationShield<T, E>( | ||
| _ operation: () throws(E) -> T, | ||
| file: String = #fileID, line: Int = #line | ||
| ) throws(E) -> T | ||
|
|
||
| public nonisolated(nonsending) func withTaskCancellationShield<T, E>( | ||
| _ operation: nonisolated(nonsending) () async throws(E) -> T, // FIXME: order of attrs | ||
| file: String = #fileID, line: Int = #line | ||
| ) async throws(E) -> T |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we give the generic types a slightly more descriptive name so it shows up nicely in the docs. On the PR that introduced nonisolated(nonsending) to the withTaskCancellationHandler methods we used Return and Failure for those two generic types.
| public func withTaskCancellationShield<T, E>( | |
| _ operation: () throws(E) -> T, | |
| file: String = #fileID, line: Int = #line | |
| ) throws(E) -> T | |
| public nonisolated(nonsending) func withTaskCancellationShield<T, E>( | |
| _ operation: nonisolated(nonsending) () async throws(E) -> T, // FIXME: order of attrs | |
| file: String = #fileID, line: Int = #line | |
| ) async throws(E) -> T | |
| public func withTaskCancellationShield<Result, Failure>( | |
| _ operation: () throws(Failure) -> Result, | |
| file: String = #fileID, line: Int = #line | |
| ) throws(Failure) -> Result | |
| public nonisolated(nonsending) func withTaskCancellationShield<Result, Failure>( | |
| _ operation: nonisolated(nonsending) () async throws(Failure) -> Result, // FIXME: order of attrs | |
| file: String = #fileID, line: Int = #line | |
| ) async throws(Failure) -> Result |
| await withTaskCancellationShield { | ||
| await withDiscardingTaskGroup { group in | ||
| group.addTask { ... } | ||
| group.cancelAll() // cancels all tasks within the group, as expected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is perfect and exactly how I expected it.
|
|
||
| func cleanup() { | ||
| withTaskCancellationShield { | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this missing a slowOperation call here?
|
|
||
| ```swift | ||
| extension Task where Success == Never, Failure == Never { | ||
| public static func isCancelled(ignoringCancellationShield: Bool) -> Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 I think that's great for debugging purposes
|
|
||
| ## Motivation | ||
|
|
||
| Task cancellation is _final_ and can not be ignored or undone. Once a task has been cancelled, it remains cancelled for the rest of its existance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Task cancellation is _final_ and can not be ignored or undone. Once a task has been cancelled, it remains cancelled for the rest of its existance. | |
| Task cancellation is _final_ and can not be ignored or undone. Once a task has been cancelled, it remains cancelled for the rest of its existence. |
|
|
||
| Doing nothing is always an option, and we suggest developers have to keep using the unstructured task workaround. | ||
|
|
||
| This doesn't seem viable though as the problem indeed is real, and the workaround is problematic scheduling wise, and may not even be usable in certain situations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may not even be usable in certain situations
is the only example of this the synchronous context case cited above, or are there others?
Introduce a proposal for task cancellation shields to allow certain code to execute regardless of task cancellation status.
Implementation WIP PR: swiftlang/swift#85637